<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>俄罗斯方块</title>
    <script src="./lodash.min.js"></script>
    <style>
      .container {
        width: 200px;
        height: 360px;
        position: relative;
        background: black;
        background-size: 200px 360px;
      }
      .activity_model {
        width: 20px;
        height: 20px;
        border: 0.3px solid #333333;
        box-sizing: border-box;
        position: absolute;
        background: #ffd75e url("logo.png") center no-repeat;
        background-size: 15px;
      }
      .fixed_model {
        width: 20px;
        height: 20px;
        border: 0.3px solid #fefefe;
        box-sizing: border-box;
        background: #bbbbbb url("logo.png") center no-repeat;
        background-size: 15px;
        position: absolute;
      }
    </style>
  </head>
  <body onload="init()">
    <div id="container" class="container"></div>

    <script>
      var STEP = 20;

      var ROW_COUNT = 18,
        COL_COUNT = 10;

      var MODELS = [
        {
          0: {
            row: 2,
            col: 0,
          },
          1: {
            row: 2,
            col: 1,
          },
          2: {
            row: 2,
            col: 2,
          },
          3: {
            row: 1,
            col: 2,
          },
        },
        {
          0: {
            row: 1,
            col: 1,
          },
          1: {
            row: 0,
            col: 0,
          },
          2: {
            row: 1,
            col: 0,
          },
          3: {
            row: 2,
            col: 0,
          },
        },
        {
          0: {
            row: 1,
            col: 1,
          },
          1: {
            row: 2,
            col: 1,
          },
          2: {
            row: 1,
            col: 2,
          },
          3: {
            row: 2,
            col: 2,
          },
        },
        {
          0: {
            row: 0,
            col: 0,
          },
          1: {
            row: 0,
            col: 1,
          },
          2: {
            row: 0,
            col: 2,
          },
          3: {
            row: 0,
            col: 3,
          },
        },
        {
          0: {
            row: 1,
            col: 1,
          },
          1: {
            row: 1,
            col: 2,
          },
          2: {
            row: 2,
            col: 2,
          },
          3: {
            row: 2,
            col: 3,
          },
        },
      ];

      var currentModle = {};
      var currentX = 0;
      var currentY = 0;

      var fixedBlocks = {};

      var mInterval = null;

      function init() {
        createModle();
        onKeydown();
      }

      function createModle() {
        if (isGameOver()) {
          gameOver();
          return;
        }

        currentModle = MODELS[_.random(0, MODELS.length - 1)];
        currentX = 0;
        currentY = 0;

        for (var key in currentModle) {
          var divEle = document.createElement("div");
          divEle.className = "activity_model";
          document.getElementById("container").appendChild(divEle);
        }

        locationBlocks();

        autoDown();
      }

      function locationBlocks() {
        checkBound();

        var eles = document.getElementsByClassName("activity_model");
        for (var i = 0; i < eles.length; i++) {
          var activityModelEle = eles[i];

          var blockModel = currentModle[i];

          activityModelEle.style.top =
            (blockModel.row + currentY) * STEP + "px";
          activityModelEle.style.left =
            (blockModel.col + currentX) * STEP + "px";
        }
      }

      function onKeydown() {
        document.onkeydown = function (event) {
          switch (event.keyCode) {
            case 38:
              console.log("上");
              rotate();
              break;
            case 39:
              console.log("右");
              move(1, 0);
              break;
            case 40:
              console.log("下");
              move(0, 1);
              break;
            case 37:
              console.log("左");
              move(-1, 0);
              break;
          }
        };
      }
      function move(x, y) {
        if (isMeet(currentX + x, currentY + y, currentModle)) {
          if (y != 0) {
            flexBottomModel();
          }
          return;
        }

        currentX += x;
        currentY += y;

        locationBlocks();
      }

      function rotate() {
        var cloneCurrentModle = _.cloneDeep(currentModle);

        for (var key in cloneCurrentModle) {
          var blockModel = cloneCurrentModle[key];

          var temp = blockModel.row;
          blockModel.row = blockModel.col;
          blockModel.col = 3 - temp;
        }

        if (isMeet(currentX, currentY, cloneCurrentModle)) {
          return;
        }
        currentModle = cloneCurrentModle;
        locationBlocks();
      }

      function checkBound() {
        var leftBound = 0;
        rightBound = COL_COUNT;
        bottomBound = ROW_COUNT;

        for (var key in currentModle) {
          var blockModel = currentModle[key];

          if (blockModel.col + currentX < leftBound) {
            currentX++;
          }

          if (blockModel.col + currentX >= rightBound) {
            currentX--;
          }

          if (blockModel.row + currentY >= bottomBound) {
            currentY--;

            flexBottomModel();
          }
        }
      }

      function flexBottomModel() {
        var activityModelEles =
          document.getElementsByClassName("activity_model");
        for (var i = activityModelEles.length - 1; i >= 0; i--) {
          var activityModelEle = activityModelEles[i];

          activityModelEle.className = "fixed_model";

          var blockModel = currentModle[i];
          fixedBlocks[
            currentY + blockModel.row + "_" + (currentX + blockModel.col)
          ] = activityModelEle;
        }

        isRemoveLine();

        createModle();
      }

      function isMeet(x, y, model) {
        for (var key in model) {
          var blockModel = model[key];

          if (fixedBlocks[y + blockModel.row + "_" + (x + blockModel.col)]) {
            return true;
          }
        }
        return false;
      }

      function isRemoveLine() {
        for (var i = 0; i < ROW_COUNT; i++) {
          var flag = true;

          for (var j = 0; j < COL_COUNT; j++) {
            if (!fixedBlocks[i + "_" + j]) {
              flag = false;
              break;
            }
          }

          if (flag) {
            removeLine(i);
          }
        }
      }

      function removeLine(line) {
        for (var i = 0; i < COL_COUNT; i++) {
          document
            .getElementById("container")
            .removeChild(fixedBlocks[line + "_" + i]);

          fixedBlocks[line + "_" + i] = null;
        }
        dropLine(line);
      }

      function dropLine(line) {
        for (var i = line - 1; i >= 0; i--) {
          for (var j = 0; j < COL_COUNT; j++) {
            if (!fixedBlocks[i + "_" + j]) continue;

            fixedBlocks[i + 1 + "_" + j] = fixedBlocks[i + "_" + j];

            fixedBlocks[i + 1 + "_" + j].style.top = (i + 1) * STEP + "px";

            fixedBlocks[i + "_" + j] = null;
          }
        }
      }

      function autoDown() {
        if (mInterval) {
          clearInterval(mInterval);
        }
        mInterval = setInterval(function () {
          move(0, 1);
        }, 600);
      }

      function isGameOver() {
        for (var i = 0; i < COL_COUNT; i++) {
          if (fixedBlocks["0_" + i]) {
            return true;
          }
        }
        return false;
      }

      function gameOver() {
        if (mInterval) {
          clearInterval(mInterval);
        }

        alert("游戏结束!");
      }
    </script>
  </body>
</html>
